Skip to content

ENH: Add lazy copy for take and between_time #50476

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 12 commits into from
Jan 13, 2023

Conversation

phofl
Copy link
Member

@phofl phofl commented Dec 28, 2022

@@ -3779,6 +3779,8 @@ def _take(

See the docstring of `take` for full explanation of the parameters.
"""
if axis == 0 and np.array_equal(indices, np.arange(0, len(self))):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we do a quick check of how costly this is compared to the actual take? (to ensure we don't introduce a performance regression for the other cases)

Maybe could also first check if the length of indices is equal to len(self)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe could also first check if the length of indices is equal to len(self)

np.array_equal actually already does that, so doing that ourselves is not needed

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I profiled this, the cost is reduced if the DataFrame gets larger.

The actual problem is a bit different though: array_equal has no early exit, even if the first value is different, it checks the whole array (wanted to bring this up tomorrow as well). We should probably write something ourselves, because I guess we will need that a couple of times.

@phofl
Copy link
Member Author

phofl commented Jan 7, 2023

Switched to array_equal_fast here

phofl and others added 2 commits January 7, 2023 15:41
Comment on lines +3799 to +3801
and array_equal_fast(
indices,
np.arange(0, len(self), dtype=np.intp),
Copy link
Member

@jorisvandenbossche jorisvandenbossche Jan 11, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Further idea to potentially speed this up: right now we only use array_equal_fast to check an array against a standard 0...n indexer, I think?
For that specific case, we don't actually need to create this second array, but could just use the iteration variable inside array_equal_fast (it only needs the length).

(now, I don't know if we would want to start using array_equal_fast for other cases)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(that also avoids creating this additional array even for the fast cases where the length doesn't even match)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I’ll take a look at this in a follow up if ok to check how big the performance improvement would be

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure

@@ -481,6 +481,39 @@ def test_assign_drop_duplicates(using_copy_on_write, method):
tm.assert_frame_equal(df, df_orig)


@pytest.mark.parametrize("obj", [Series([1, 2]), DataFrame({"a": [1, 2]})])
def test_take(using_copy_on_write, obj):
obj_orig = obj.copy()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Small nitpick: can you add a comment here that is testing the corner case of taking all rows? (because in general take always by definition returns a copy)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added

@jorisvandenbossche jorisvandenbossche merged commit 62521da into pandas-dev:main Jan 13, 2023
@phofl phofl deleted the cow_take branch January 13, 2023 08:23
phofl added a commit to phofl/pandas that referenced this pull request Jan 13, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants